package com.hucii.hc_connectivity;


import android.Manifest;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.net.wifi.WifiNetworkSpecifier;
import android.net.wifi.WifiNetworkSuggestion;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.Settings;

import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.util.ArrayList;
import java.util.List;

import io.flutter.Log;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.PluginRegistry;

/**
 * Reports connectivity related information such as connectivity type and wifi information.
 */
public class Connectivity  {
    private Context context;
    private ConnectivityManager connectivityManager;
    private Activity activity;
    private WifiManager wifiManager;
    private final ConnectPermissions connectPermissions;
    private ConnectPermissions.PermissionsRegistry permissionsRegistry;
    private static final String TAG = "ConnectivityFlutter";
    private List<WifiNetworkSuggestion> networkSuggestions;
    private List<WifiNetworkSuggestion> suggestionsToBeRemovedOnExit = new ArrayList<>();
    private ConnectivityManager.NetworkCallback networkCallback;
    private List<String> ssidsToBeRemovedOnExit = new ArrayList<String>();
    private static final int PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION = 656889658;
    private static final int PERMISSIONS_REQUEST_CODE_LOCATION_HARDWARE = 656889659;
    @VisibleForTesting
    static final int REQUEST_CODE_CHOOSE_WIFI_SETTING = 656889660;

    private  MethodChannel.Result setWifiResult;

    public Connectivity(ConnectivityManager connectivityManager, WifiManager wifiManager, Context context, ConnectPermissions connectPermissions) {
        this.wifiManager = wifiManager;
        this.connectivityManager = connectivityManager;
        this.context = context;
        this.connectPermissions = connectPermissions;

    }


    public final PluginRegistry.ActivityResultListener resultListener =
            new PluginRegistry.ActivityResultListener() {
                @Override
                public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
                    if (requestCode == REQUEST_CODE_CHOOSE_WIFI_SETTING) {
                        if(setWifiResult!=null){
                            final WifiInfo wifiInfo = getWifiInfo();
                            String ssid = null;
                            if (wifiInfo != null) ssid = wifiInfo.getSSID();
                            if (ssid != null) ssid = ssid.replaceAll("\"", ""); // Android returns "SSID"
                            if (ssid != null && ssid.equals("<unknown ssid>")) ssid = "";
                            setWifiResult.success(ssid);
                        }

                    }
                    return false;
                }
            };





    public void setActivity(Activity activity) {
        this.activity = activity;
    }

    public void requestPermissions(ConnectPermissions.ResultCallback callback) {
        connectPermissions.requestPermissions(activity, permissionsRegistry, callback);
    }

    public void setPermissionsRegistry(ConnectPermissions.PermissionsRegistry permissionsRegistry) {
        this.permissionsRegistry = permissionsRegistry;

    }

    String getWifiName() {
        if (!checkPermissions()) {
            return null;
        }
        final WifiInfo wifiInfo = getWifiInfo();
        String ssid = null;
        if (wifiInfo != null) ssid = wifiInfo.getSSID();
        if (ssid != null) ssid = ssid.replaceAll("\"", ""); // Android returns "SSID"
        if (ssid != null && ssid.equals("<unknown ssid>")) ssid = null;
        return ssid;
    }

    String getWifiBSSID() {
        if (!checkPermissions()) {
            return null;
        }
        final WifiInfo wifiInfo = getWifiInfo();
        String bssid = null;
        if (wifiInfo != null) {
            bssid = wifiInfo.getBSSID();
        }
        return bssid;
    }

    String getWifiIPAddress() {
        WifiInfo wifiInfo = null;
        if (wifiManager != null) wifiInfo = wifiManager.getConnectionInfo();

        String ip = null;
        int i_ip = 0;
        if (wifiInfo != null) i_ip = wifiInfo.getIpAddress();

        if (i_ip != 0)
            ip =
                    String.format(
                            "%d.%d.%d.%d",
                            (i_ip & 0xff), (i_ip >> 8 & 0xff), (i_ip >> 16 & 0xff), (i_ip >> 24 & 0xff));

        return ip;
    }

    private WifiInfo getWifiInfo() {
        return wifiManager == null ? null : wifiManager.getConnectionInfo();
    }

    private Boolean checkPermissions() {


        boolean grantedNetworkState =
                ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_NETWORK_STATE)
                        == PackageManager.PERMISSION_GRANTED;


        boolean grantedChangeWifiState =
                ContextCompat.checkSelfPermission(context, Manifest.permission.CHANGE_WIFI_STATE)
                        == PackageManager.PERMISSION_GRANTED;

        boolean grantedAccessFine =
                ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED;

        boolean grantedAccessCoarse =
                ContextCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED;

//        boolean grantedNetworkSettings =
//                ContextCompat.checkSelfPermission(context,"android.Manifest.permission.NETWORK_SETTINGS")
//                        == PackageManager.PERMISSION_GRANTED;
//        if (!grantedNetworkSettings) {
//            ActivityCompat.requestPermissions(
//                    activity, new String[]{"android.Manifest.permission.NETWORK_SETTINGS"},
//                    PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION);
//
//        }

        if (!grantedAccessFine) {
            ActivityCompat.requestPermissions(
                    activity, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION);
            return false;
        }


        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P
                && !grantedChangeWifiState
                && !grantedAccessFine
                && !grantedAccessCoarse
                && !grantedNetworkState) {
            if(!grantedChangeWifiState){
                ActivityCompat.requestPermissions(
                        activity, new String[]{Manifest.permission.CHANGE_WIFI_STATE},
                        PERMISSIONS_REQUEST_CODE_ACCESS_FINE_LOCATION);
            }

            Log.w(
                    TAG,
                    "Attempted to get Wi-Fi data that requires additional permission(s).\n"
                            + "To successfully get WiFi Name or Wi-Fi BSSID starting with Android O, please ensure your app has one of the following permissions:\n"
                            + "- CHANGE_WIFI_STATE\n"
                            + "- ACCESS_FINE_LOCATION\n"
                            + "- ACCESS_COARSE_LOCATION\n"
                            + "For more information about Wi-Fi Restrictions in Android 8.0 and above, please consult the following link:\n"
                            + "https://developer.android.com/guide/topics/connectivity/wifi-scan");
            return false;
        }

        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P && !grantedChangeWifiState) {
            Log.w(
                    TAG,
                    "Attempted to get Wi-Fi data that requires additional permission(s).\n"
                            + "To successfully get WiFi Name or Wi-Fi BSSID starting with Android P, please ensure your app has the CHANGE_WIFI_STATE permission.\n"
                            + "For more information about Wi-Fi Restrictions in Android 9.0 and above, please consult the following link:\n"
                            + "https://developer.android.com/guide/topics/connectivity/wifi-scan");
            return false;
        }

        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.P
                && !grantedAccessFine
                && !grantedAccessCoarse) {
            Log.w(
                    TAG,
                    "Attempted to get Wi-Fi data that requires additional permission(s).\n"
                            + "To successfully get WiFi Name or Wi-Fi BSSID starting with Android P, additional to CHANGE_WIFI_STATE please ensure your app has one of the following permissions too:\n"
                            + "- ACCESS_FINE_LOCATION\n"
                            + "- ACCESS_COARSE_LOCATION\n"
                            + "For more information about Wi-Fi Restrictions in Android 9.0 and above, please consult the following link:\n"
                            + "https://developer.android.com/guide/topics/connectivity/wifi-scan");
            return false;
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
                && (!grantedAccessFine || !grantedChangeWifiState)) {

            Log.w(
                    TAG,
                    "Attempted to get Wi-Fi data that requires additional permission(s).\n"
                            + "To successfully get WiFi Name or Wi-Fi BSSID starting with Android Q, please ensure your app has the CHANGE_WIFI_STATE and ACCESS_FINE_LOCATION permission.\n"
                            + "For more information about Wi-Fi Restrictions in Android 10.0 and above, please consult the following link:\n"
                            + "https://developer.android.com/guide/topics/connectivity/wifi-scan");

            return false;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            LocationManager locationManager =
                    (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);

            boolean locationEnabled = locationManager.isLocationEnabled();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P && !locationEnabled) {
                openGpsSettings();
                Log.w(
                        TAG,
                        "Attempted to get Wi-Fi data that requires additional permission(s).\n"
                                + "To successfully get WiFi Name or Wi-Fi BSSID starting with Android P, please ensure Location services are enabled on the device (under Settings > Location).\n"
                                + "For more information about Wi-Fi Restrictions in Android 9.0 and above, please consult the following link:\n"
                                + "https://developer.android.com/guide/topics/connectivity/wifi-scan");
                return false;
            }
        }


        return true;
    }

    /**
     * 打开Gps设置界面
     */
    private void openGpsSettings() {
        Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
        context.startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
    }

    public String check() {
        if (!checkPermissions()) {
            return "";
        }

        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
            wifiManager.startScan();
        }
        return handleNetworkScanResult().toString();
    }

    String getNetworkType() {
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            Network network = connectivityManager.getActiveNetwork();
            NetworkCapabilities capabilities = connectivityManager.getNetworkCapabilities(network);
            if (capabilities == null) {
                return "none";
            }
            if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI)
                    || capabilities.hasTransport(NetworkCapabilities.TRANSPORT_ETHERNET)) {
                return "wifi";
            }
            if (capabilities.hasTransport(NetworkCapabilities.TRANSPORT_CELLULAR)) {
                return "mobile";
            }
        }

        return getNetworkTypeLegacy();
    }

    @SuppressWarnings("deprecation")
    private String getNetworkTypeLegacy() {
        // handle type for Android versions less than Android 9
        android.net.NetworkInfo info = connectivityManager.getActiveNetworkInfo();
        if (info == null || !info.isConnected()) {
            return "none";
        }
        int type = info.getType();
        switch (type) {
            case ConnectivityManager.TYPE_ETHERNET:
            case ConnectivityManager.TYPE_WIFI:
            case ConnectivityManager.TYPE_WIMAX:
                return "wifi";
            case ConnectivityManager.TYPE_MOBILE:
            case ConnectivityManager.TYPE_MOBILE_DUN:
            case ConnectivityManager.TYPE_MOBILE_HIPRI:
                return "mobile";
            default:
                return "none";
        }
    }

    public ConnectivityManager getConnectivityManager() {
        return connectivityManager;
    }

    public boolean isEnabled() {
        return wifiManager.isWifiEnabled();
    }

    public void setEnabled(MethodCall poCall, MethodChannel.Result poResult) {
        Boolean enabled = poCall.argument("state");
        poResult.success(wifiManager.setWifiEnabled(enabled));
    }

    /// Use this method to check if the device is currently connected to Wifi.
    public void isConnected(MethodChannel.Result poResult) {
        if (!checkPermissions()) {
            return;
        }
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
            isConnectedDeprecated(poResult);
        } else {
            int PERMISSIONS_REQUEST_CODE_ACCESS_NETWORK_STATE = 656889657;
            boolean result = false;
            if (connectivityManager != null) {
                // `connManager.getActiveNetwork` only return if the network has internet
                // therefore using `connManager.getAllNetworks()` to check all networks
                for (final Network network : connectivityManager.getAllNetworks()) {
                    final NetworkCapabilities capabilities = network != null
                            ? connectivityManager.getNetworkCapabilities(network)
                            : null;
                    final boolean isConnected = capabilities != null && capabilities.hasTransport(NetworkCapabilities.TRANSPORT_WIFI);
                    if (isConnected) {
                        result = true;
                        break;
                    }
                }
            }

            poResult.success(result);
        }
    }


    public void connect(final MethodCall poCall, final MethodChannel.Result poResult) {
        new Thread() {
            public void run() {
                String ssid = poCall.argument("ssid");
                String password = poCall.argument("password");
                String security = poCall.argument("security");
                Boolean joinOnce = poCall.argument("join_once");
                Boolean withInternet = poCall.argument("with_internet");

                connectTo(poResult, ssid, password, security, joinOnce, withInternet);

            }
        }.start();
    }

    public void openWifiNetwork(final MethodCall poCall, final MethodChannel.Result poResult) {
        if (!checkPermissions()) {
            poResult.success("");
            return;
        }

        // if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
        //     wifiManager.startScan();
        //     final WifiInfo wifiInfo = getWifiInfo();
        //     String ssid = null;
        //     if (wifiInfo != null) ssid = wifiInfo.getSSID();
        //     if (ssid != null) ssid = ssid.replaceAll("\"", ""); // Android returns "SSID"
        //     if (ssid != null && ssid.equals("<unknown ssid>")) ssid = "";
        //     poResult.success(ssid);
        //     return;
        // }else{
            setWifiResult=poResult;
            Intent it = new Intent(Settings.ACTION_WIFI_SETTINGS);
//                ComponentName cn = new ComponentName("com.android.settings","com.android.settings.WirelessSettings");
//                it.setComponent(cn);
            activity.startActivityForResult(it,REQUEST_CODE_CHOOSE_WIFI_SETTING);
        // }
    }


    public void forceWifiUsage(final MethodCall poCall, final MethodChannel.Result poResult) {
        boolean useWifi = poCall.argument("useWifi");

        boolean success = true;
        boolean shouldReply = true;
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP && connectivityManager != null) {
            if (useWifi) {
                NetworkRequest.Builder builder;
                builder = new NetworkRequest.Builder();
                /// set the transport type do WIFI
                builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
                shouldReply = false;
                connectivityManager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
                    @Override
                    public void onAvailable(Network network) {
                        super.onAvailable(network);
                        boolean success = false;
                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                            success = connectivityManager.bindProcessToNetwork(network);

                        } else {
                            success = ConnectivityManager.setProcessDefaultNetwork(network);
                        }
                        connectivityManager.unregisterNetworkCallback(this);
                        final boolean result = success;
                        final Handler handler = new Handler(Looper.getMainLooper());
                        handler.post(new Runnable() {
                            @Override
                            public void run() {
                                poResult.success(result);
                            }
                        });
                    }
                });

            } else {
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                    success = connectivityManager.bindProcessToNetwork(null);
                } else {
                    success = ConnectivityManager.setProcessDefaultNetwork(null);
                }
            }

        }
        if (shouldReply) {
            poResult.success(success);
        }
    }


    /// Disconnect current Wifi.
    public void disconnect(MethodChannel.Result poResult) {
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            //noinspection deprecation
            wifiManager.disconnect();
        } else {
            if (networkCallback != null) {
                connectivityManager.unregisterNetworkCallback(networkCallback);
            }
            if (networkSuggestions != null) {
                wifiManager.removeNetworkSuggestions(networkSuggestions);
            }
        }
        poResult.success(null);
    }

    /**
     * Registers a wifi network in the device wireless networks
     * For API >= 30 uses intent to permanently store such network in user configuration
     * For API <= 29 uses deprecated functions that manipulate directly
     * *** registerWifiNetwork :
     * param ssid, SSID to register
     * param password, passphrase to use
     * param security, security mode (WPA or null) to use
     * return {@code true} if the operation succeeds, {@code false} otherwise
     */
    public void registerWifiNetwork(final MethodCall poCall, final MethodChannel.Result poResult) {
        if (!checkPermissions()) {
            poResult.success(false);
        }
        String ssid = poCall.argument("ssid");
        String password = poCall.argument("password");
        String security = poCall.argument("security");

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            final WifiNetworkSuggestion.Builder suggestedNet = new WifiNetworkSuggestion.Builder();
            suggestedNet.setSsid(ssid);

            if (security != null && security.toUpperCase().equals("WPA")) {
                suggestedNet.setWpa2Passphrase(password);
            } else if (security != null && security.toUpperCase().equals("WEP")) {
                // WEP is not supported
                poResult.error("Error", "WEP is not supported for Android SDK " + Build.VERSION.SDK_INT, "");
                return;
            }

            final ArrayList<WifiNetworkSuggestion> suggestionsList = new ArrayList<WifiNetworkSuggestion>();
            suggestionsList.add(suggestedNet.build());

            Bundle bundle = new Bundle();
            bundle.putParcelableArrayList(android.provider.Settings.EXTRA_WIFI_NETWORK_LIST, suggestionsList);
            Intent intent = new Intent(android.provider.Settings.ACTION_WIFI_ADD_NETWORKS);
            intent.putExtras(bundle);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);

            poResult.success(true);
        } else {
            // Deprecated version
            android.net.wifi.WifiConfiguration conf = generateConfiguration(ssid, password, security);

            int updateNetwork = registerWifiNetworkDeprecated(conf);

            if (updateNetwork == -1) {
                poResult.error("Error", "Error updating network configuration", "");
            } else {
                poResult.success(true);
            }
        }
    }


    /// This method will remove the WiFi network as per the passed SSID from the device list
    public void removeWifiNetwork(MethodCall poCall, MethodChannel.Result poResult) {
        String prefix_ssid = poCall.argument("ssid");
        if (prefix_ssid.equals("")) {
            poResult.error("Error", "No prefix SSID was given!", null);
        }

        List<android.net.wifi.WifiConfiguration> mWifiConfigList = wifiManager.getConfiguredNetworks();
        for (android.net.wifi.WifiConfiguration wifiConfig : mWifiConfigList) {
            String comparableSSID = ('"' + prefix_ssid); //Add quotes because wifiConfig.SSID has them
            if (wifiConfig.SSID.startsWith(comparableSSID)) {
                wifiManager.removeNetwork(wifiConfig.networkId);
                wifiManager.saveConfiguration();
                poResult.success(true);
                return;
            }
        }
        poResult.success(false);
    }


    public JSONArray handleNetworkScanResult() {
        List<ScanResult> results = wifiManager.getScanResults();
        JSONArray wifiArray = new JSONArray();

        try {
            for (ScanResult result : results) {
                JSONObject wifiObject = new JSONObject();
                if (!result.SSID.equals("")) {

                    wifiObject.put("SSID", result.SSID);
                    wifiObject.put("BSSID", result.BSSID);
                    wifiObject.put("capabilities", result.capabilities);
                    wifiObject.put("frequency", result.frequency);
                    wifiObject.put("level", result.level);
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
                        wifiObject.put("timestamp", result.timestamp);
                    } else {
                        wifiObject.put("timestamp", 0);
                    }
                    /// Other fields not added
                    //wifiObject.put("operatorFriendlyName", result.operatorFriendlyName);
                    //wifiObject.put("venueName", result.venueName);
                    //wifiObject.put("centerFreq0", result.centerFreq0);
                    //wifiObject.put("centerFreq1", result.centerFreq1);
                    //wifiObject.put("channelWidth", result.channelWidth);

                    wifiArray.put(wifiObject);
                }
            }
        } catch (JSONException e) {
            e.printStackTrace();
        } finally {
            return wifiArray;
        }
    }


    /// Method to connect to WIFI Network
    private void connectTo(final MethodChannel.Result poResult, final String ssid, final String password, final String security, final Boolean joinOnce, final Boolean withInternet) {
        final Handler handler = new Handler(Looper.getMainLooper());
        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
            final boolean connected = connectToDeprecated(ssid, password, security, joinOnce);
            handler.post(new Runnable() {
                @Override
                public void run() {
                    poResult.success(connected);
                }
            });
        } else {
            // error if WEP security, since not supported
            if (security != null && security.toUpperCase().equals("WEP")) {
                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        poResult.error("Error", "WEP is not supported for Android SDK " + Build.VERSION.SDK_INT, "");
                    }
                });
                return;
            }

            if (withInternet != null && withInternet) {
                // create network suggestion
                final WifiNetworkSuggestion.Builder builder = new WifiNetworkSuggestion.Builder();
                // set ssid
                builder.setSsid(ssid);
                // set password
                if (security != null && security.toUpperCase().equals("WPA")) {
                    builder.setWpa2Passphrase(password);
                }

                // remove suggestions if already existing
                if (networkSuggestions != null) {
                    wifiManager.removeNetworkSuggestions(networkSuggestions);
                }

                //builder.setIsAppInteractionRequired(true);
                final WifiNetworkSuggestion suggestion = builder.build();

                networkSuggestions = new ArrayList<>();
                networkSuggestions.add(suggestion);
                if (joinOnce != null && joinOnce) {
                    suggestionsToBeRemovedOnExit.add(suggestion);
                }

                final int status = wifiManager.addNetworkSuggestions(networkSuggestions);
                Log.e(TAG, "status: " + status);

                handler.post(new Runnable() {
                    @Override
                    public void run() {
                        poResult.success(status == WifiManager.STATUS_NETWORK_SUGGESTIONS_SUCCESS);
                    }
                });
            } else {
                // Make new network specifier
                final WifiNetworkSpecifier.Builder builder = new WifiNetworkSpecifier.Builder();
                // set ssid
                builder.setSsid(ssid);
                // set security
                if (security != null && security.toUpperCase().equals("WPA")) {
                    builder.setWpa2Passphrase(password);
                }

                final NetworkRequest networkRequest = new NetworkRequest.Builder()
                        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                        .removeCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET)
                        .setNetworkSpecifier(builder.build())
                        .build();


                if (networkCallback != null)
                    connectivityManager.unregisterNetworkCallback(networkCallback);

                networkCallback = new ConnectivityManager.NetworkCallback() {
                    boolean resultSent = false;

                    @Override
                    public void onAvailable(@NonNull Network network) {
                        super.onAvailable(network);
                        if (!resultSent) {
                            poResult.success(true);
                            resultSent = true;
                        }
                    }

                    @Override
                    public void onUnavailable() {
                        super.onUnavailable();
                        if (!resultSent) {
                            poResult.success(false);
                            resultSent = true;
                        }
                    }
                };

                connectivityManager.requestNetwork(networkRequest, networkCallback, handler, 30 * 1000);
            }
        }
    }


    @SuppressWarnings("deprecation")
    private void isConnectedDeprecated(MethodChannel.Result poResult) {

        android.net.NetworkInfo mWifi = connectivityManager != null
                ? connectivityManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI)
                : null;

        poResult.success(mWifi != null && mWifi.isConnected());
    }

    private WifiConfiguration IsExsits(String ssid){
        List<WifiConfiguration> mWifiConfigList = wifiManager.getConfiguredNetworks();
        if (mWifiConfigList != null) {
            for (android.net.wifi.WifiConfiguration wifiConfig : mWifiConfigList) {
                if (wifiConfig.SSID.equals(ssid)) {
                    return wifiConfig;
                }
            }
        }
        return null;
    }

    private android.net.wifi.WifiConfiguration generateConfiguration(String ssid, String password, String security) {
        android.net.wifi.WifiConfiguration conf = new android.net.wifi.WifiConfiguration();

        if (security != null) security = security.toUpperCase();
        else security = "NONE";

        if (password == null) {
            conf.hiddenSSID = false;
            conf.status = WifiConfiguration.Status.ENABLED;
            conf.SSID = "\"" + ssid + "\"";
            if (security.toUpperCase().equals("WEP")) {
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
                conf.wepTxKeyIndex = 0;
                conf.wepKeys[0] = "";
            } else if (security.toUpperCase().equals("PSK")) {
                conf.preSharedKey = "";
            } else if (security.toUpperCase().equals("EAP")) {
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_EAP);
                conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
                conf.preSharedKey = "";
            } else {
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                conf.preSharedKey = null;
            }
        } else {
            conf.allowedAuthAlgorithms.clear();
            conf.allowedGroupCiphers.clear();
            conf.allowedKeyManagement.clear();
            conf.allowedPairwiseCiphers.clear();
            conf.allowedProtocols.clear();
            conf.SSID = "\"" + ssid + "\"";
            WifiConfiguration tempConfig = IsExsits(conf.SSID);
            if (tempConfig != null) {
                wifiManager.removeNetwork(tempConfig.networkId);
            }
            if (security.toUpperCase().equals("WEP")) {
                conf.preSharedKey = "\"" + password + "\"";
                conf.hiddenSSID = true;
                conf.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                conf.wepTxKeyIndex = 0;
            } else if (security.toUpperCase().equals("WPA")) {
                conf.hiddenSSID = true;
                conf.preSharedKey = "\"" + password + "\"";
                conf.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
                conf.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
                conf.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
                conf.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
            } else {
                conf.wepKeys[0] = "";
                conf.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
                conf.wepTxKeyIndex = 0;
            }
        }

        return conf;
    }


    @SuppressWarnings("deprecation")
    private int registerWifiNetworkDeprecated(android.net.wifi.WifiConfiguration conf) {
//        int updateNetwork = -1;
//
//        /// Remove the existing configuration for this netwrok
//        List<android.net.wifi.WifiConfiguration> mWifiConfigList = wifiManager.getConfiguredNetworks();
//
//        if (mWifiConfigList != null) {
//            for (android.net.wifi.WifiConfiguration wifiConfig : mWifiConfigList) {
//                if (wifiConfig.SSID.equals(conf.SSID)) {
//                    conf.networkId = wifiConfig.networkId;
//                    wifiConfig.preSharedKey = conf.preSharedKey;
//                    updateNetwork = wifiManager.updateNetwork(wifiConfig);
//                } else {
//                    wifiManager.disableNetwork(wifiConfig.networkId);
//                }
//            }
//        }
//
//        /// If network not already in configured networks add new network
//        if (updateNetwork == -1) {
//            updateNetwork = wifiManager.addNetwork(conf);
//            wifiManager.saveConfiguration();
//        }

//        return updateNetwork;

        int networkId = wifiManager.addNetwork(conf);
        wifiManager.saveConfiguration();
        return networkId;
    }


    @SuppressWarnings("deprecation")
    private Boolean connectToDeprecated(String ssid, String password, String security, Boolean joinOnce) {
        /// Make new configuration
        android.net.wifi.WifiConfiguration conf = generateConfiguration(ssid, password, security);

//        int updateNetwork = registerWifiNetworkDeprecated(conf);
        int updateNetwork = -1;
        List<android.net.wifi.WifiConfiguration> mWifiConfigList = wifiManager.getConfiguredNetworks();

        if (mWifiConfigList != null) {
            for (android.net.wifi.WifiConfiguration wifiConfig : mWifiConfigList) {
                if (wifiConfig.SSID.equals(conf.SSID)) {
                    updateNetwork = wifiConfig.networkId;
                }
                wifiManager.disableNetwork(wifiConfig.networkId);
            }
        }
        if (updateNetwork == -1) {
            updateNetwork = registerWifiNetworkDeprecated(conf);
        }

        if (updateNetwork == -1) {
            return false;
        }

        if (joinOnce != null && joinOnce.booleanValue()) {
            ssidsToBeRemovedOnExit.add(conf.SSID);
        }

        boolean disconnect = wifiManager.disconnect();
//        try {
//            Thread.sleep(1000);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//        if (!disconnect) {
//            return false;
//        }

        boolean enabled = wifiManager.enableNetwork(updateNetwork, true);
        if (!enabled) return false;

        boolean connected = false;
        for (int i = 0; i < 30; i++) {
            int networkId = wifiManager.getConnectionInfo().getNetworkId();
            if (networkId != -1) {
                connected = networkId == updateNetwork;
                break;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException ignored) {
                break;
            }
        }
        if (false) {
            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP && connectivityManager != null) {
                NetworkRequest.Builder builder;
                builder = new NetworkRequest.Builder();
                /// set the transport type do WIFI
                builder.addTransportType(NetworkCapabilities.TRANSPORT_WIFI);
                connectivityManager.requestNetwork(builder.build(), new ConnectivityManager.NetworkCallback() {
                    @Override
                    public void onAvailable(Network network) {

                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {


                            connectivityManager.bindProcessToNetwork(null);

                            connectivityManager.bindProcessToNetwork(network);


                        } else {
                            //This method was deprecated in API level 23
                            ConnectivityManager.setProcessDefaultNetwork(null);

                            ConnectivityManager.setProcessDefaultNetwork(network);

                        }

                        connectivityManager.unregisterNetworkCallback(this);

                    }
                });

            }
        }


        return connected;
    }

}
